/* components */
import BaseSelectUser from '@src/component/common/BaseSelectUser/BaseSelectUser'
import { BaseSelectUserInput } from '@src/component/common/BaseSelectUser/components'
/* model */
import { 
  BaseSelectUserDefaultMultiAllOptions,
  BaseSelectUserDefaultMultiDepartmentAndRoleOptions,
  BaseSelectUserDefaultMultiDepartmentAndUserOptions,
  BaseSelectUserDefaultMultiDepartmentOptions,
  BaseSelectUserDefaultMultiDepartmentUserOptions,
  BaseSelectUserDefaultMultiServiceProviderOptions,
  BaseSelectUserDefaultMultiUserOptions,
  BaseSelectUserDefaultSingleUserOptions,
  BaseSelectUserOptions, 
  BaseSelectUserPropsOptions, 
  BaseSelectUserResult,
  SelectUserComponentUser 
} from '@src/component/common/BaseSelectUser/model'
import MsgModel from '@model/MsgModel'
/* store */
import store, { DefaultBaseSelectUserStoreState, BaseSelectUserVuexPropertyEnum } from '@src/component/common/BaseSelectUser/store'
/* util */
import fastCall from '@src/component/util/fastCall'
import Log from '@src/util/log'
/* vue */
import Vue, { VueConstructor } from 'vue'
import { computed } from 'vue';
/* hooks */
import { useTabCurrent } from '@src/component/common/BaseSelectUser/hooks/useFrameTab';

/* util */
import { 
  getOptionsMax,
  getMountElement, 
  getOptionsTitle, 
  getOptionsIsBind,
  getOptionsIsCheckStrictly,
  getOptionsUnique,
  getBaseSelectUserResultBySelectUserItems,
  getOptionsSelected,
  getOptionsIsCanChooseUser,
  getOptionsIsCanChooseDepartment,
  getOptionsIsCanChooseRole,
  getOptionsIsCanChooseServiceProvider,
  getOptionsShowServiceProvider,
  getOptionsShowRole,
  getOptionsShowProjectTeam,
  getOptionsShowDelete,
  getOptionsShowNoDistribute,
  getOptionsShowCancel,
  getOptionsIsShowUser,
  getOptionsIsShowSearch,
  getOptionsFetchDepartmentList,
  getOptionsFetchDepartmentUserList,
  getOptionsBaseWindowOptions,
  getOptionsIsTag,
  getOptionsIsAuthKey,
  getOptionsShowDepartment,
  getOptionsFetchSearchUserList,
  getOptionsFetchProjectTeamList,
  getOptionsFetchProjectTeamUserList,
  getOptionsFetchSearchMoreUserList,
  getOptionsIsShowSearchOrganizationUsers,
  getOptionsIsShowSearchServiceProvidersUsers,
  getOptionsTop,
  getOptionsIsNeedEmail,
  getOptionsIsShowDynamic,
  getOptionsRenderDynamicContent,
  getOptionsRenderDynamicName,
  getOptionsRenderIsScreenSelect,
  getOptionsRenderIsRenderFilterContent,
  getOptionsRenderRenderFilterContent,
  getOptionsCurrentTabType,
  getOptionsShowTagIfSpUser,
  getOptionsShowSpAll,
  getOptionsIsTrigger,
  getOptionsIsOnlyShowBusinessServiceCloudRole,
  getOptionsIsHideNullProvider,
  getOptionsGetInstance,
  getOptionsAsyncConfirm
} from '@src/component/common/BaseSelectUser/util'
import { destroyComponent } from '@src/util/dom'
import { cloneDeep } from 'lodash'
/* types */
import { 
  BaseSelectUserComponentResultType,
  BaseSelectUserMultiAllOptionsType, 
  BaseSelectUserMultiDepartmentAndRoleOptionsType, 
  BaseSelectUserMultiDepartmentAndUserOptionsType, 
  BaseSelectUserMultiDepartmentOptionsType, 
  BaseSelectUserMultiDepartmentUserOptionsType, 
  BaseSelectUserMultiServiceProviderOptionsType, 
  BaseSelectUserMultiUserOptionsType, 
  BaseSelectUserSelectedItemType, 
  BaseSelectUserSingleUserOptionsType 
} from '@src/component/common/BaseSelectUser/types'

import { useNewVue } from '@hooks/useNewVue'
import { findComponentDownward } from '@src/util/assist'
const { createVue } = useNewVue();

/** 
 * @description 选人组件 选择方法
 * @param {BaseSelectUserOptions} options 选人组件配置项
 * @returns {BaseSelectUserComponentResultType} 选择结果
*/
function choose(options: BaseSelectUserOptions = {}): BaseSelectUserComponentResultType {
  
  Log.info(options, 'options', choose.name)
  
  try {
    
    return renderBaseSelectUserComponent(options)
    
  } catch (error: any) {
    
    Log.error(error, renderBaseSelectUserComponent.name)
    
    return (
      Promise.resolve(
        buildErrorResult(error)
      )
    )
    
  }
  
}

/** 
 * @description 选人组件 - 单选 - 选人
*/
function chooseSingleUser(options: BaseSelectUserSingleUserOptionsType): BaseSelectUserComponentResultType {
  const newOptions: BaseSelectUserOptions = Object.assign({}, options, BaseSelectUserDefaultSingleUserOptions)
  return choose(newOptions)
}

/** 
 * @description 选人组件 - 多选 - 选人
*/
function chooseMultiUser(options: BaseSelectUserMultiUserOptionsType): BaseSelectUserComponentResultType {
  const newOptions: BaseSelectUserOptions = Object.assign({}, BaseSelectUserDefaultMultiUserOptions, options)
  return choose(newOptions)
}

/** 
 * @description 选人组件 - 多选 - 选部门
*/
function chooseMultiDepartment(options: BaseSelectUserMultiDepartmentOptionsType): BaseSelectUserComponentResultType {
  const newOptions: BaseSelectUserOptions = Object.assign({}, options, BaseSelectUserDefaultMultiDepartmentOptions)
  return choose(newOptions)
}

/** 
 * @description 选人组件 - 多选 - 选部门中人员
*/
function chooseMultiDepartmentUser(options: BaseSelectUserMultiDepartmentUserOptionsType): BaseSelectUserComponentResultType {
  const newOptions: BaseSelectUserOptions = Object.assign({}, options, BaseSelectUserDefaultMultiDepartmentUserOptions)
  return choose(newOptions)
}

/** 
 * @description 选人组件 - 多选 - 选部门和角色
*/
function chooseMultiDepartmentAndRole(options: BaseSelectUserMultiDepartmentAndRoleOptionsType): BaseSelectUserComponentResultType {
  const newOptions: BaseSelectUserOptions = Object.assign({}, options, BaseSelectUserDefaultMultiDepartmentAndRoleOptions)
  return choose(newOptions)
}

/** 
 * @description 选人组件 - 多选 - 选部门和人
*/
function chooseMultiDepartmentAndUser(options: BaseSelectUserMultiDepartmentAndUserOptionsType): BaseSelectUserComponentResultType {
  const newOptions: BaseSelectUserOptions = Object.assign({}, options, BaseSelectUserDefaultMultiDepartmentAndUserOptions)
  return choose(newOptions)
}

/** 
 * @description 选人组件 - 多选 - 服务商
*/
function chooseMultiServiceProvider(options: BaseSelectUserMultiServiceProviderOptionsType): BaseSelectUserComponentResultType {
  const newOptions: BaseSelectUserOptions = Object.assign({}, options, BaseSelectUserDefaultMultiServiceProviderOptions)
  return choose(newOptions)
}

/** 
 * @description 选人组件 - 多选 - 全部类型(部门、角色、服务商、人员)
*/
function chooseMultiAll(options: BaseSelectUserMultiAllOptionsType): BaseSelectUserComponentResultType {
  const newOptions: BaseSelectUserOptions = Object.assign({}, BaseSelectUserDefaultMultiAllOptions, options)
  return choose(newOptions)
}

/** 
 * @description 渲染基础选人组件
 * @param {BaseSelectUserOptions} options 选人组件配置项
 * @returns {Promise<MsgModel<BaseSelectUserResult>>} 选择结果
*/
function renderBaseSelectUserComponent(options: BaseSelectUserOptions): Promise<MsgModel<BaseSelectUserResult>> {
  
  const attrs = {
    props: buildBaseSelectUserProps(options)
  }
  
  const getInstanceFunc = getOptionsGetInstance(options)
  
  // 获取组件挂载元素
  const mountElement = getMountElement(options)
  
  // 初始化 store 中的 state
  store.replaceState(cloneDeep(DefaultBaseSelectUserStoreState))
  
  return (
    new Promise<MsgModel<BaseSelectUserResult>>((resolve, reject) => {
      
      const instance = createVue({
        el: mountElement,
        components: {
          [BaseSelectUser.name]: BaseSelectUser
        },
        methods: {
          /** 
           * @description 监听单选选择事件
          */
          onSingleChoiceUserHandler(users: SelectUserComponentUser[]) {
            
            const baseSelectUserResult = getBaseSelectUserResultBySelectUserItems(users)
            const result = buildSuccessResult(baseSelectUserResult)
            
            this.onDestroyHandler()
            
            resolve(result)
            
          },
          /** 
           * @description 监听 多选选择事件
          */
          onMultiChoiceHandler(items: BaseSelectUserSelectedItemType[]) {
            
            const baseSelectUserResult = getBaseSelectUserResultBySelectUserItems(items)
            const result = buildSuccessResult(baseSelectUserResult)
            
            this.onDestroyHandler()
            
            resolve(result)
            
          },
          /** 
           * @description 监听关闭/取消事件
          */
          onCloseHandler() {
            
            const result = buildCancelResult()
            
            this.onDestroyHandler()
            
            reject(result)
            
          },
          /** 
           * @description 监听销毁事件
          */
          onDestroyHandler() {
            setTimeout(() => destroyComponent(this), 300)
          },
          /** 
           * @description 关闭事件
           * -- 支持外部调用的
          */
          close() {
            this.$refs.BaseSelectUser.close()
          }
        },
        mounted(){
          // 是否需要将组件绑定到tab
          this.$nextTick(()=>{
            
            if(!attrs.props?.baseWindowOptions?.id) return;
            
            const id = `#layx-${attrs.props?.baseWindowOptions?.id}`;
            let bindTabElement: any = document.querySelector(id);
            
            
            if(options.isBind){
              const currentTab = useTabCurrent();
              const bindTabInfo = computed(() => store.state.bindTabInfo);
              
              const tabComponents = {
                ...bindTabInfo.value,
                [currentTab.id]: {
                  close: () => {
                    if(!bindTabElement) return;
                    
                    const baseWindowComponent = findComponentDownward(this, 'base-window')
                    baseWindowComponent?.closeWindow()
                    
                    this.onDestroyHandler()
                    bindTabElement.parentElement?.removeChild(bindTabElement);
                  },
                  show() {
                    if(!bindTabElement) return;
                    
                    setTimeout(()=>{
                      bindTabElement.style.setProperty('display', 'block', 'important');
                      const layxMain = bindTabElement.querySelector(".layx-main");
                      layxMain.style.height = '500px';
                    })
                    // bindTabElement.style.display = 'block';
                  },
                  hidden() {
                    if(!bindTabElement) return;
                    bindTabElement.style.setProperty('display', 'none', 'important');
                  }
                }
              }
          
              store.commit(BaseSelectUserVuexPropertyEnum.SetBindTabInfo, tabComponents);
            }
          })
        },
        render() {
          return (
            <BaseSelectUser
              ref="BaseSelectUser"
              options={attrs.props}
              onSingle={this.onSingleChoiceUserHandler}
              onMulti={this.onMultiChoiceHandler}
              onClose={this.onCloseHandler}
              onDestroy={this.onDestroyHandler}
            >
            </BaseSelectUser>
          )
        }
      })
      
      getInstanceFunc(instance)
      
    })
  )
}

/** 
 * @description 构建基础选人组件 props
 * @param {BaseSelectUserOptions} options 选人组件配置项
 * @returns {BaseSelectUserPropsOptions} 基础选人组件 props
*/
function buildBaseSelectUserProps(options: BaseSelectUserOptions): BaseSelectUserPropsOptions {
  
  const max = getOptionsMax(options)
  const title = getOptionsTitle(options)
  const selected = getOptionsSelected(options)
  const isBind = getOptionsIsBind(options)
  const isCheckStrictly = getOptionsIsCheckStrictly(options)
  const unique = getOptionsUnique(options)
  const isCanChooseUser = getOptionsIsCanChooseUser(options)
  const isCanChooseDepartment = getOptionsIsCanChooseDepartment(options)
  const isCanChooseRole = getOptionsIsCanChooseRole(options)
  const isCanChooseServiceProvider = getOptionsIsCanChooseServiceProvider(options)
  const showServiceProvider = getOptionsShowServiceProvider(options)
  const showRole = getOptionsShowRole(options)
  const showProjectTeam = getOptionsShowProjectTeam(options)
  const showDepartment = getOptionsShowDepartment(options)
  const showDelete = getOptionsShowDelete(options)
  const showNoDistribute = getOptionsShowNoDistribute(options)
  const showCancel = getOptionsShowCancel(options)
  const isShowUser = getOptionsIsShowUser(options)
  const baseWindowOptions = getOptionsBaseWindowOptions(options)
  const isTag = getOptionsIsTag(options)
  const top = getOptionsTop(options)
  const isNeedEmail = getOptionsIsNeedEmail(options)
  const isTrigger = getOptionsIsTrigger(options)
  const isShowDynamic = getOptionsIsShowDynamic(options)
  const currentTabType = getOptionsCurrentTabType(options)
  const showTagIfSpUser = getOptionsShowTagIfSpUser(options)
  const showSpAll = getOptionsShowSpAll(options)
  const authKey = getOptionsIsAuthKey(options)
  const hideNullProvider = getOptionsIsHideNullProvider(options)
  const isShowSearch = getOptionsIsShowSearch(options)
  const isShowSearchOrganizationUsers = getOptionsIsShowSearchOrganizationUsers(options)
  const isShowSearchServiceProviderUsers = getOptionsIsShowSearchServiceProvidersUsers(options)
  const isOnlyShowBusinessServiceCloudRole = getOptionsIsOnlyShowBusinessServiceCloudRole(options)

  const fetchDepartmentList = getOptionsFetchDepartmentList(options)
  const fetchDepartmentUserList = getOptionsFetchDepartmentUserList(options)
  const fetchSearchUserList = getOptionsFetchSearchUserList(options)
  const fetchProjectTeamList = getOptionsFetchProjectTeamList(options)
  const fetchProjectTeamUserList = getOptionsFetchProjectTeamUserList(options)
  const fetchSearchMoreUserList = getOptionsFetchSearchMoreUserList(options)
  
  const renderDynamicContent = getOptionsRenderDynamicContent(options)
  const DynamicTabName = getOptionsRenderDynamicName(options)
  const isScreenSelect = getOptionsRenderIsScreenSelect(options)
  const isRenderFilterContent = getOptionsRenderIsRenderFilterContent(options)
  const renderFilterContent = getOptionsRenderRenderFilterContent(options)
  const asyncConfirm = getOptionsAsyncConfirm(options)
  
  return {
    max,
    title,
    isBind,
    isCheckStrictly,
    unique,
    selected,
    isCanChooseUser,
    isCanChooseDepartment,
    isCanChooseRole,
    isCanChooseServiceProvider,
    showServiceProvider,
    showRole,
    showProjectTeam,
    showDepartment,
    showDelete,
    showNoDistribute,
    showCancel,
    isShowUser,
    baseWindowOptions,
    isTag,
    top,
    isNeedEmail,
    isShowDynamic,
    showTagIfSpUser,
    showSpAll,
    authKey,
    hideNullProvider,

    isOnlyShowBusinessServiceCloudRole,
    isShowSearch,
    isShowSearchOrganizationUsers,
    isShowSearchServiceProviderUsers,
    
    isTrigger,
    
    fetchDepartmentList,
    fetchDepartmentUserList,
    fetchSearchUserList,
    fetchProjectTeamList,
    fetchProjectTeamUserList,
    fetchSearchMoreUserList,
    currentTabType,
    
    renderDynamicContent,
    DynamicTabName,
    isScreenSelect,
    isRenderFilterContent,
    renderFilterContent,
    asyncConfirm
  }
}

/** 
 * @description 构建成功结果
 * @param {BaseSelectUserResult} baseSelectUserResult 基础选人组件结果
 * @returns {MsgModel<BaseSelectUserResult>} 成功结果
*/
function buildSuccessResult(baseSelectUserResult: BaseSelectUserResult): MsgModel<BaseSelectUserResult> {
  return new MsgModel(MsgModel.SUCCESS, 'ok', baseSelectUserResult)
}

/** 
 * @description 构建取消结果
 * @returns {MsgModel<BaseSelectUserResult>} 取消结果
*/
function buildCancelResult() {
  return new MsgModel(MsgModel.FAIL, 'cancel', new BaseSelectUserResult())
}

/** 
 * @description 构建错误结果
 * @returns {MsgModel<BaseSelectUserResult>} 错误结果
*/
function buildErrorResult(error: Error) {
  return new MsgModel(MsgModel.FAIL, error.message, new BaseSelectUserResult())
}

const props = {
  single: {
    user: chooseSingleUser
  },
  multi: {
    user: chooseMultiUser,
    department: chooseMultiDepartment,
    departmentUser: chooseMultiDepartmentUser,
    departmentAndUser: chooseMultiDepartmentAndUser,
    departmentAndRole: chooseMultiDepartmentAndRole,
    serviceProvider: chooseMultiServiceProvider,
    all: chooseMultiAll
  }
}

/** 
 * @description 选人组件
 * @see https://publink.yuque.com/docs/share/14a5c525-1842-4a59-b09a-1435b8e3592b?# 《PC 端使用文档》
*/
const BaseContact = {
  install(vue: VueConstructor) {
    fastCall(vue, 'select', props)
    vue.component(BaseSelectUserInput.name, BaseSelectUserInput)
  },
  namespace: 'select',
  props
}

export * from '@src/component/common/BaseSelectUser/model'
export * from '@src/component/common/BaseSelectUser/types'
export * from '@src/component/common/BaseSelectUser/util'
export * from '@src/component/common/BaseSelectUser/api'
export * from '@src/component/common/BaseSelectUser/store'
export * from '@src/component/common/BaseSelectUser/hooks'
export * from '@src/component/common/BaseSelectUser/components'

export default BaseContact;
